<template>
	<div class="my-canvas-data">
		<el-button plain round icon="Plus" class="m-b-10 w100" style="border-style: dashed" @click="insertFn()">
			新 增
		</el-button>
		<n-list>
			<n-list-item v-for="(item, i) in apiList" :key="item.reqID" class="p-l-10 p-y-5">
				{{ item.name }}
				<template #suffix>
					<el-space>
						<el-button icon="Edit" circle link @click="insertFn(item, i)" />
						<el-button icon="DeleteFilled" circle link @click="apiList.splice(i, 1)" />
					</el-space>
				</template>
			</n-list-item>
		</n-list>

		<!-- 新增api弹窗 -->
		<el-dialog title="请求接口" v-model="dialog.open" width="1200px" append-to-body @closed="resetForm(refDialogForm)">
			<div class="flex">
				<my-form
					class="f1"
					ref="refDialogForm"
					:model="dialog.form"
					label-width="80px"
					:formItem="[
						{ prop: 'name', label: '名称', required: true },
						{
							prop: 'requestDataType',
							label: '请求方式',
							itemType: 'select',
							list: [
								{
									label: '动态请求',
									value: '1'
								},
								{
									label: '外部接口',
									value: '3'
								}
							],
							fileType: { label: 'label', value: 'value' },
							required: true,
							col: { span: 6 },
							onChange: () => {
								dialog.form.reqID = '';
							}
						},
						{
							prop: 'sourceID',
							label: '数据源',
							itemType: 'select',
							list: sourceOptions,
							fileType: { label: 'title', value: 'id' },
							required: dialog.form.requestDataType == 1,
							col: { span: 6 },
							if: dialog.form.requestDataType == 1
						},
						{
							prop: 'reqID',
							label: '接口',
							itemType: 'select',
							list: reqInterfaceOptions,
							fileType: { label: 'sqlName', value: 'id' },
							required: dialog.form.requestDataType == 1,
							col: { span: 6 },
							if: dialog.form.requestDataType == 1
						},
						{
							prop: 'reqID',
							label: '外部接口',
							itemType: 'select',
							list: OutApiOptions,
							fileType: { label: 'name', value: 'id' },
							required: dialog.form.requestDataType == 3,
							col: { span: 6 },
							if: dialog.form.requestDataType == 3
						},
						{
							itemType: 'select',
							prop: 'requestInterval',
							label: '更新间隔',
							col: { span: 6 }
						}
					]"
				>
					<template #requestInterval="{ model, prop }">
						<my-input-number v-model="model[prop]">
							<template #append>
								<my-select
									v-model="model.requestIntervalUnit"
									:clearable="false"
									:list="[
										{ dictLabel: '秒', dictValue: '秒' },
										{ dictLabel: '分', dictValue: '分' },
										{ dictLabel: '时', dictValue: '时' },
										{ dictLabel: '天', dictValue: '天' }
									]"
									style="width: 90px"
								/>
							</template>
						</my-input-number>
					</template>
				</my-form>
				<el-button :disabled="!dialog.form.reqID" class="m-l-10" type="primary" @click.prevent="fetchTargetData()"
					>测试</el-button
				>
			</div>
			<n-card :bordered="false" role="dialog" size="small" :aria-modal="true" style="width: 100%; height: 400px">
				<div class="flex">
					<n-space vertical class="w50">
						<n-tag type="info">
							<span class="func-keyword">function</span>&nbsp;&nbsp;filter(data, res)&nbsp;&nbsp;{
						</n-tag>
						<my-monaco-editor v-model="dialog.form.filter" width="569px" height="300px" language="javascript" />
						<n-tag type="info">}</n-tag>
					</n-space>
					<div class="w50 flex">
						<n-divider vertical class="h100" />
						<n-scrollbar style="max-height: 370px">
							<n-space :size="15" vertical>
								<div class="p-10">
									<n-text depth="3">默认过滤数据(data)：</n-text>
									<n-code :code="toString(sourceData?.data) || '暂无'" language="json" :word-wrap="true"></n-code>
								</div>
								<div class="p-10">
									<n-text depth="3">接口返回数据(res)：</n-text>
									<n-code :code="toString(sourceData) || '暂无'" language="json" :word-wrap="true"></n-code>
								</div>
								<div class="p-10">
									<n-text depth="3">过滤器结果：</n-text>
									<n-code :code="filterRes || '暂无'" language="json" :word-wrap="true"></n-code>
								</div>
							</n-space>
						</n-scrollbar>
					</div>
				</div>
			</n-card>
			<template #footer>
				<n-space justify="space-between">
					<div class="flex s-center">
						<n-tag :bordered="false" type="primary">
							<template #icon>
								<my-icon icon="DocumentText" />
							</template>
							规则
						</n-tag>
						<n-text class="m-l-10" depth="2">过滤器默认处理接口返回值的「data」字段</n-text>
					</div>
					<n-space>
						<el-button @click.prevent="dialog.open = false">取 消</el-button>
						<el-button type="primary" @click.prevent="dialogSubmitFn()">确 定</el-button>
					</n-space>
				</n-space>
			</template>
		</el-dialog>
	</div>
</template>

<script setup>
// 页面请求list
const { apiList } = toRefs($store.chart.editCanvasConfig);

/********************************************** 新增api逻辑 **********************************************/
import { listSource, listArrange, listOutApi } from '@a/data';

const dialog = reactive({
		open: false,
		name: '',
		form: {
			requestInterval: 30,
			requestIntervalUnit: '秒'
		}
	}),
	refDialogForm = shallowRef(null);

// 新增信息
let editIndex;
function insertFn(data, index) {
	dialog.name = 'add';
	dialog.open = true;
	sourceData.value = '';
	nextTick(() => {
		dialog.form.filter = 'return data';
		if (data) {
			dialog.name = 'edit';
			editIndex = index;
			nextTick(() => {
				dialog.form = cloneDeep(data);
				if (dialog.form.reqID) fetchTargetData();
			});
		}
	});
}

function dialogSubmitFn() {
	fetchTargetData(() => {
		if (errorFlag.value) {
			msgError('过滤函数错误，无法进行保存');
			return;
		}
		refDialogForm.value.$refs.refMyForm.validate((valid) => {
			if (valid) {
				if (dialog.name === 'add') apiList.value.push({ ...dialog.form });
				if (dialog.name === 'edit') apiList.value[editIndex] = { ...dialog.form };

				const response = cloneDeep(sourceData.value);
				$store.chart.pageData = merge(
					$store.chart.pageData,
					new Function('data', 'res', dialog.form.filter)(response?.data, response)
				);

				nextTick(() => (dialog.open = false));
			}
		});
	});
}

// 动态请求数据
const sourceOptions = ref([]);
listSource().then((res) => {
	sourceOptions.value = res.data;
});
const reqInterfaceOptions = ref([]);
watch(
	() => dialog.form.sourceID,
	(val) => {
		if (val) {
			listArrange({ dataSourceId: val }).then((res) => {
				reqInterfaceOptions.value = res.data;
			});
		}
	},
	{ immediate: true }
);

// 外部接口数据
let OutApiOptions = ref([]);
listOutApi().then((res) => {
	OutApiOptions.value = res.data;
});

/********************************************** 数据filter逻辑 **********************************************/
import { toString } from '@/utils';
import { resultArrange, resultOutApi } from '@a/data';

const sourceData = ref(''),
	errorFlag = ref(true);

// 请求接口获取数据
async function fetchTargetData(callBack) {
	try {
		if (dialog.form.reqID) {
			const res = await (dialog.form.requestDataType == 1 ? resultArrange : resultOutApi)({ id: dialog.form.reqID });
			if (res) {
				sourceData.value = res;
				callBack?.();
				return;
			}
			msgWarning('没有拿到返回值，请检查接口！');
		}
	} catch (error) {
		console.error(error);
		msgWarning('数据异常，请检查参数！');
	}
}

// 过滤结果
const filterRes = computed(() => {
	try {
		if (sourceData.value) {
			// new Function() 可以接n个参数，最后一个参数作为函数体。
			const fn = new Function('data', 'res', dialog.form.filter);
			const response = cloneDeep(sourceData.value);
			const res = fn(response?.data, response);
			errorFlag.value = false;
			return toString(res);
		}
	} catch (error) {
		errorFlag.value = true;
		return `过滤函数错误，日志：${error}`;
	}
});
</script>

<style lang="scss" scoped>
@include b(canvas-data) {
	padding-top: 20px;
}
</style>
